import { nextTick } from 'vue';
import { parseTime } from './ruoyi';
import {
  IMG_URL,
  FILE_URL,
  DOMAIN_EMAILS_VALUES,
  LOGIN_EMAILS_VALUES
} from './const';
import { exportProgress, downloadOther, downloadImage } from '@/api/login';
import { ElMessageBox } from 'element-plus';

/**
 * 表格时间格式化
 */
export function formatDate(cellValue) {
  if (cellValue == null || cellValue == '') return '';
  var date = new Date(cellValue);
  var year = date.getFullYear();
  var month =
    date.getMonth() + 1 < 10
      ? '0' + (date.getMonth() + 1)
      : date.getMonth() + 1;
  var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
  var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
  var minutes =
    date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
  var seconds =
    date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
  return (
    year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
  );
}

/**
 * @param {number} time
 * @param {string} option
 * @returns {string}
 */
export function formatTime(time, option) {
  if (('' + time).length === 10) {
    time = parseInt(time) * 1000;
  } else {
    time = +time;
  }
  const d = new Date(time);
  const now = Date.now();

  const diff = (now - d) / 1000;

  if (diff < 30) {
    return '刚刚';
  } else if (diff < 3600) {
    // less 1 hour
    return Math.ceil(diff / 60) + '分钟前';
  } else if (diff < 3600 * 24) {
    return Math.ceil(diff / 3600) + '小时前';
  } else if (diff < 3600 * 24 * 2) {
    return '1天前';
  }
  if (option) {
    return parseTime(time, option);
  } else {
    return (
      d.getMonth() +
      1 +
      '月' +
      d.getDate() +
      '日' +
      d.getHours() +
      '时' +
      d.getMinutes() +
      '分'
    );
  }
}

/**
 * @param {string} url
 * @returns {Object}
 */
export function getQueryObject(url) {
  url = url == null ? window.location.href : url;
  const search = url.substring(url.lastIndexOf('?') + 1);
  const obj = {};
  const reg = /([^?&=]+)=([^?&=]*)/g;
  search.replace(reg, (rs, $1, $2) => {
    const name = decodeURIComponent($1);
    let val = decodeURIComponent($2);
    val = String(val);
    obj[name] = val;
    return rs;
  });
  return obj;
}

/**
 * @param {string} input value
 * @returns {number} output value
 */
export function byteLength(str) {
  // returns the byte length of an utf8 string
  let s = str.length;
  for (var i = str.length - 1; i >= 0; i--) {
    const code = str.charCodeAt(i);
    if (code > 0x7f && code <= 0x7ff) s++;
    else if (code > 0x7ff && code <= 0xffff) s += 2;
    if (code >= 0xdc00 && code <= 0xdfff) i--;
  }
  return s;
}

/**
 * @param {Array} actual
 * @returns {Array}
 */
export function cleanArray(actual) {
  const newArray = [];
  for (let i = 0; i < actual.length; i++) {
    if (actual[i]) {
      newArray.push(actual[i]);
    }
  }
  return newArray;
}

/**
 * @param {Object} json
 * @returns {Array}
 */
export function param(json) {
  if (!json) return '';
  return cleanArray(
    Object.keys(json).map(key => {
      if (json[key] === undefined) return '';
      return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]);
    })
  ).join('&');
}

/**
 * @param {string} url
 * @returns {Object}
 */
export function param2Obj(url) {
  const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ');
  if (!search) {
    return {};
  }
  const obj = {};
  const searchArr = search.split('&');
  searchArr.forEach(v => {
    const index = v.indexOf('=');
    if (index !== -1) {
      const name = v.substring(0, index);
      const val = v.substring(index + 1, v.length);
      obj[name] = val;
    }
  });
  return obj;
}

/**
 * @param {string} val
 * @returns {string}
 */
export function html2Text(val) {
  const div = document.createElement('div');
  div.innerHTML = val;
  return div.textContent || div.innerText;
}

/**
 * Merges two objects, giving the last one precedence
 * @param {Object} target
 * @param {(Object|Array)} source
 * @returns {Object}
 */
export function objectMerge(target, source) {
  if (typeof target !== 'object') {
    target = {};
  }
  if (Array.isArray(source)) {
    return source.slice();
  }
  Object.keys(source).forEach(property => {
    const sourceProperty = source[property];
    if (typeof sourceProperty === 'object') {
      target[property] = objectMerge(target[property], sourceProperty);
    } else {
      target[property] = sourceProperty;
    }
  });
  return target;
}

/**
 * @param {HTMLElement} element
 * @param {string} className
 */
export function toggleClass(element, className) {
  if (!element || !className) {
    return;
  }
  let classString = element.className;
  const nameIndex = classString.indexOf(className);
  if (nameIndex === -1) {
    classString += '' + className;
  } else {
    classString =
      classString.substr(0, nameIndex) +
      classString.substr(nameIndex + className.length);
  }
  element.className = classString;
}

/**
 * @param {string} type
 * @returns {Date}
 */
export function getTime(type) {
  if (type === 'start') {
    return new Date().getTime() - 3600 * 1000 * 24 * 90;
  } else {
    return new Date(new Date().toDateString());
  }
}

/**
 * @param {Function} func
 * @param {number} wait
 * @param {boolean} immediate
 * @return {*}
 */
export function debounce(func, wait, immediate) {
  let timeout, args, context, timestamp, result;

  const later = function () {
    // 据上一次触发时间间隔
    const last = +new Date() - timestamp;

    // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last);
    } else {
      timeout = null;
      // 如果设定为immediate===true，因为开始边界已经调用过了此处无需调用
      if (!immediate) {
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      }
    }
  };

  return function (...args) {
    context = this;
    timestamp = +new Date();
    const callNow = immediate && !timeout;
    // 如果延时不存在，重新设定延时
    if (!timeout) timeout = setTimeout(later, wait);
    if (callNow) {
      result = func.apply(context, args);
      context = args = null;
    }

    return result;
  };
}

/**
 * @param {Function} func
 * @param {number} wait // 停止后多少毫秒会触发一次
 * @param {boolean} mustRun 每过多少毫秒会触发一次
 * @return {*}
 */
export function throttle(func, wait, mustRun) {
  let timeout,
    startTime = new Date();
  return function () {
    let context = this,
      args = arguments,
      curTime = new Date();
    clearTimeout(timeout);
    if (curTime - startTime >= mustRun) {
      func.apply(context, args);
      startTime = curTime;
    } else {
      timeout = setTimeout(function () {
        func.apply(context, args);
      }, wait);
    }
  };
}

/**
 * This is just a simple version of deep copy
 * Has a lot of edge cases bug
 * If you want to use a perfect deep copy, use lodash's _.cloneDeep
 * @param {Object} source
 * @returns {Object}
 */
export function deepClone(source) {
  if (!source && typeof source !== 'object') {
    throw new Error('error arguments', 'deepClone');
  }
  const targetObj = source.constructor === Array ? [] : {};
  Object.keys(source).forEach(keys => {
    if (source[keys] && typeof source[keys] === 'object') {
      targetObj[keys] = deepClone(source[keys]);
    } else {
      targetObj[keys] = source[keys];
    }
  });
  return targetObj;
}

/**
 * @param {Array} arr
 * @returns {Array}
 */
export function uniqueArr(arr) {
  return Array.from(new Set(arr));
}

/**
 * @returns {string}
 */
export function createUniqueString() {
  const timestamp = +new Date() + '';
  const randomNum = parseInt((1 + Math.random()) * 65536) + '';
  return (+(randomNum + timestamp)).toString(32);
}

/**
 * Check if an element has a class
 * @param {HTMLElement} elm
 * @param {string} cls
 * @returns {boolean}
 */
export function hasClass(ele, cls) {
  return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}

/**
 * Add class to element
 * @param {HTMLElement} elm
 * @param {string} cls
 */
export function addClass(ele, cls) {
  if (!hasClass(ele, cls)) ele.className += ' ' + cls;
}

/**
 * Remove class from element
 * @param {HTMLElement} elm
 * @param {string} cls
 */
export function removeClass(ele, cls) {
  if (hasClass(ele, cls)) {
    const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
    ele.className = ele.className.replace(reg, ' ');
  }
}

export function makeMap(str, expectsLowerCase) {
  const map = Object.create(null);
  const list = str.split(',');
  for (let i = 0; i < list.length; i++) {
    map[list[i]] = true;
  }
  return expectsLowerCase ? val => map[val.toLowerCase()] : val => map[val];
}

// 首字母大小
export function titleCase(str) {
  return str.replace(/( |^)[a-z]/g, L => L.toUpperCase());
}

// 下划转驼峰
export function camelCase(str) {
  return str.replace(/_[a-z]/g, str1 => str1.substr(-1).toUpperCase());
}

export function isNumberStr(str) {
  return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str);
}

// url上传成功后，添加到反显列表
export function addFileList(opts) {
  let { fileList, links = [] } = opts;
  const list = [...fileList];
  links.forEach(url => {
    if (!url) return;
    list.push({
      resUrl: url,
      uid: Date.now() + '-' + Math.random(),
      status: 'success',
      url: IMG_URL(url)
    });
  });
  return list;
}

export function validUpload(list, activeModules, form) {
  if (!activeModules.includes('email_logo')) return true;

  list = list || [];
  for (let i = 0; i < list.length; i++) {
    const item = list[i];
    if (item.status !== 'success') {
      $msg.warning('有图片正在上传中，请稍等');
      return false;
    }
  }
  return true;
}

// 下载图片
export function downloadImgs(urls, name, loading) {
  loading.value = true;
  urls.forEach(url => {
    downloadImage({ uri: url })
      .then(res => {
        const url = URL.createObjectURL(res);
        handleDownload([url], name);
      })
      .finally(() => {
        loading.value = false;
      });
  });
}

export function handleDownload(urls, name) {
  urls.forEach(link => {
    const image = new Image();
    // 解决跨域问题
    image.setAttribute('crossOrigin', 'anonymous');
    image.src = link;
    image.onload = () => {
      const canvas = document.createElement('canvas');
      canvas.width = image.width;
      canvas.height = image.height;
      const context = canvas.getContext('2d');
      context.drawImage(image, 0, 0, image.width, image.height);
      const url = canvas.toDataURL('image/png'); // 图片 base64
      const a = document.createElement('a');
      //  + '.png' 定义文件拓展名、防止因为name中有.号导致.png文件拓展名丢失
      a.download = name + '.png';
      a.href = url;
      const event = new MouseEvent('click');
      a.dispatchEvent(event);
    };
  });
}

// 第三方图片下载
export function downloadOtherImg(url, name, loading) {
  loading.value = true;
  downloadOther({ url })
    .then(res => {
      const url = URL.createObjectURL(res);
      downloadImgs([url], name);
    })
    .finally(() => {
      loading.value = false;
    });
}

// 处理多选下拉，带全部的交互逻辑
// formData-表单 key-该字段key allValue-全部选项的value
export function initMultipleData(formData, key, allValue) {
  const value = formData[key];
  if (!value.length || value[value.length - 1] === allValue) {
    formData[key] = [allValue];
  } else if (value.includes(allValue)) {
    const index = value.findIndex(it => it === allValue);
    formData[key].splice(index, 1);
    // 虽然很迷惑，但这里只能这样操作，否则级联选择器会产生异常
    const newValue = formData[key];
    formData[key] = [];
    nextTick(() => {
      formData[key] = newValue;
    });
  }
}

// 导出
export function exportExcel(opts) {
  let time;
  clearTimeout(time);
  const { loading, api, params, progress, formItems } = opts;
  loading.value = true;
  progress.value = 0;
  const newParams = { ...(params || {}) };
  Object.keys(newParams).forEach(code => {
    if (formItems?.[code]?.showOnly) delete newParams[code];
  });
  api(newParams)
    .then(res => {
      clearTimeout(time);
      const resData = res.data || {};
      if (resData.status === 1) {
        progress.value = resData.progress;
        time = setTimeout(() => {
          deepExport(opts, resData.id);
        }, 1000);
      }
      if (resData.status === 2) {
        progress.value = resData.progress;
        loading.value = false;
        ElMessageBox({
          title: '导出下载确认',
          message: `导出完成，是否立即下载？`,
          type: 'warning',
          confirmButtonText: '立即下载',
          cancelButtonText: '取消',
          showCancelButton: true,
          closeOnClickModal: false,
          closeOnPressEscape: false
        })
          .then(() => {
            window.open(FILE_URL(resData.store_uri));
          })
          .catch(() => {
            console.log('取消下载导出文件');
          });
      }
      if (resData.status === 3) {
        loading.value = false;
        $msg.error(resData.message);
      }
    })
    .catch(() => {
      loading.value = false;
    });
}

// 轮询导出
function deepExport(opts, id) {
  let time;
  clearTimeout(time);
  const { loading, progress } = opts;
  exportProgress({ id })
    .then(res => {
      clearTimeout(time);
      const resData = res.data || {};
      if (resData.status === 1) {
        progress.value = resData.progress;
        time = setTimeout(() => {
          deepExport(opts, resData.id);
        }, 1000);
      }
      if (resData.status === 2) {
        progress.value = resData.progress;
        loading.value = false;
        ElMessageBox({
          title: '导出下载确认',
          message: `导出完成，是否立即下载？`,
          type: 'warning',
          confirmButtonText: '立即下载',
          cancelButtonText: '取消',
          showCancelButton: true,
          closeOnClickModal: false,
          closeOnPressEscape: false
        })
          .then(() => {
            window.open(FILE_URL(resData.store_uri));
          })
          .catch(() => {
            console.log('取消下载导出文件');
          });
      }
      if (resData.status === 3) {
        loading.value = false;
        $msg.error(resData.message);
      }
    })
    .catch(() => {
      loading.value = false;
    });
}

// 删除参数的所有空字符串
export function initParams(params) {
  Object.keys(params).forEach(key => {
    if (params[key] === '') delete params[key];
    if (Object.prototype.toString.call(params[key]).includes('Object')) {
      initParams(params[key]);
    }
  });
}

// 处理编辑表单
export function initEditParams(_form) {
  // 业务组ID
  _form.business_group_id =
    _form.business_group_id || _form?.business_group?.id;

  // 团队ID
  _form.group_id = _form.group_id || _form?.group?.id;

  // 站点信息
  _form.site_info = _form.site_info || {};
  const _site_info = _form.site_info;

  // 店小秘
  _site_info.dian_xiao_mi = _site_info.dian_xiao_mi || _form.dian_xiao_mi;

  // 域名初始化
  _site_info.domain_initialize_id =
    _site_info.domain_initialize_id || _form.domain_initialize?.id;

  // 申请域名
  _site_info.domain = _site_info.domain || _form.domain;

  // 分配域名
  _site_info.assigned_domain =
    _site_info.assigned_domain || _form.assigned_domain;

  // 域名用途
  _site_info.domain_usage =
    _site_info.domain_usage || (_form.domain_usage || []).map(item => item.id);

  // 站点类型
  _site_info.site_type = _site_info.site_type || _form.site_type?.id;

  // 域名邮箱
  _site_info.domain_emails = _site_info.domain_emails || _form.domain_emails;

  // 登录邮箱
  _site_info.login_emails = _site_info.login_emails || _form.login_emails;

  // 管理账号
  _site_info.login_account = _site_info.login_account || _form.login_account;

  // 邮箱模板
  _site_info.email_template_ids =
    _site_info.email_template_ids ||
    (_form.email_template || []).map(item => item.id);

  // 邮箱用途
  _site_info.email_usage_id =
    _site_info.email_usage_id || _form.email_usage?.id;

  // 托管类型
  _site_info.hosting_type_id =
    _site_info.hosting_type_id || _form.hosting_type?.id;

  // 站点模式
  _site_info.site_mode_id = _site_info.site_mode_id || _form.site_mode?.id;

  // 模板站域名
  _site_info.template_site_domain =
    _site_info.template_site_domain || _form.template_site_domain;

  // logo
  _site_info.logo = _site_info.logo || _form.logo;

  // 处理数组字段 & 特殊字段

  // 域名邮箱默认一条
  if (!_form.site_info.domain_emails?.length) {
    _form.site_info.domain_emails = [''];
  }

  // 登录邮箱默认一条
  if (!_form.site_info.login_emails?.length) {
    _form.site_info.login_emails = [''];
  }

  // 管理账号默认一条
  if (!_form.site_info.login_account?.length) {
    _form.site_info.login_account = [''];
  }

  // 将logo处理成文件格式
  const logo = _form.site_info.logo;
  _form.imgList = addFileList({
    fileList: [],
    links: logo ? [logo] : []
  });
}

// 校验邮箱
export const validEmail = (site_info, activeModules, form) => {
  site_info = site_info || {};
  let domainEmails = [];
  let loginEmails = [];
  if (activeModules.includes('domain_email')) {
    domainEmails = site_info.domain_emails || [];
  }
  if (activeModules.includes('login_email')) {
    loginEmails = site_info.login_emails || [];
  }
  if (
    !activeModules.includes('domain_email') &&
    !activeModules.includes('login_email')
  ) {
    return true;
  }

  const obj1 = {};
  for (let i = domainEmails.length - 1; i >= 0; i--) {
    const item = domainEmails[i];
    if (!item) {
      domainEmails.splice(i, 1);
      continue;
    }
    obj1[item] = (obj1[item] || 0) + 1;
    if (obj1[item] > 1) {
      $msg.warning('域名邮箱不能重复');
      return false;
    }
  }

  const obj2 = {};
  for (let i = loginEmails.length - 1; i >= 0; i--) {
    const item = loginEmails[i];
    if (!item) {
      loginEmails.splice(i, 1);
      continue;
    }
    obj2[item] = (obj2[item] || 0) + 1;
    if (obj2[item] > 1) {
      $msg.warning('登录邮箱不能重复');
      return false;
    }
  }

  if (activeModules.includes('domain_email') && !domainEmails.length) {
    domainEmails.push('');
  }

  if (activeModules.includes('login_email') && !loginEmails.length) {
    loginEmails.push('');
  }

  return true;
};

// 校验管理账号
export const validAccount = (site_info, activeModules, form) => {
  site_info = site_info || {};
  if (!activeModules.includes('login_account')) {
    return true;
  }
  const accounts = site_info.login_account || [];
  const obj = {};
  for (let i = accounts.length - 1; i >= 0; i--) {
    const item = accounts[i];
    if (!item) {
      accounts.splice(i, 1);
      continue;
    }
    obj[item] = (obj[item] || 0) + 1;
    if (obj[item] > 1) {
      $msg.warning('管理账号不能重复');
      return false;
    }
  }

  if (!accounts.length) {
    accounts.push('');
  }

  return true;
};

// 复制文本
export function copyText(text, successMsg = '复制成功!') {
  // 创建input元素
  const input = document.createElement('input');
  // 赋值 - 想要复制的内容
  input.value = text;
  // 插入到文档
  document.body.appendChild(input);
  // 隐藏
  input.style.cssText = `position:fixed;clip:rect(0 0 0 0);top:-10px`;
  // 选中
  input.select();
  // 复制
  document.execCommand('copy');
  // 移除input
  document.body.removeChild(input);
  if (successMsg) $msg.success(successMsg);
}

// 表格选择事件，只能选择同一个团队
export function handleSelectionSomeGroup(opts) {
  const { list, selectList, tableRef, flagCallBack } = opts;
  selectList.value = (list || []).filter(item => {
    const flag = flagCallBack(item || {}, list?.[0] || {});
    if (!flag) {
      tableRef.value?.zxTableRef?.toggleRowSelection?.(item, false);
    }
    return flag;
  });
}

// 将字符串千分符处理
export function formatNumberWithCommas(numberStr) {
  numberStr = String(numberStr);
  if (!numberStr || numberStr === 'NaN') return;
  // 先分割整数部分和小数部分
  let [integerPart, decimalPart] = numberStr.split('.');

  // 使用正则表达式添加千分位的逗号
  integerPart = integerPart.replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');

  // 如果存在小数部分，重新拼接整个数字
  if (decimalPart !== undefined) {
    return `${integerPart}.${decimalPart}`;
  } else {
    return integerPart;
  }
}

// 获取申请类型信息
export function getDeepInfo({ list, key, field = 'id', childs = 'childs' }) {
  for (let i = 0; i < list.length; i++) {
    const item = list[i];
    if (item[field] === key) return item;
    if (item[childs]?.length) {
      const info = getDeepInfo({ list: item[childs], key, field, childs });
      if (info) return info;
    }
  }
}
